<!DOCTYPE html><html class="theme-next gemini use-motion" lang="zh-Hans"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta name="theme-color" content="#222"><script src="/MyBlog/lib/pace/pace.min.js?v=1.0.2"></script><link href="/MyBlog/lib/pace/pace-theme-loading-bar.min.css?v=1.0.2" rel="stylesheet"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><link href="/MyBlog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/MyBlog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/MyBlog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css"><link rel="apple-touch-icon" sizes="180x180" href="/MyBlog/images/apple-touch-icon-next.png?v=5.1.4"><link rel="icon" type="image/png" sizes="32x32" href="/MyBlog/images/bitbug_favicon.ico?v=5.1.4"><link rel="icon" type="image/png" sizes="16x16" href="/MyBlog/images/bitbug_favicon16.ico?v=5.1.4"><link rel="mask-icon" href="/MyBlog/images/logo.svg?v=5.1.4" color="#222"><meta name="keywords" content="Vue,"><meta name="description" content="1.什么是reactive?reactive是Vue3中提供的实现响应式数据的方法在Vue2中响应式数据是通过defineProperty来实现的,而在Vue3中响应式数据是通过ES6的Proxy来实现的reactive注意点:reactive参数必须是对象或数组(json&#x2F;arr)，否则无法变成响应式如果给reactive传递了其它对象,默认情况下修改对象，界面不会自动更新。如果想更新，可以通过"><meta property="og:type" content="article"><meta property="og:title" content="Vue3.0（三）reactive和ref"><meta property="og:url" content="https://gitee.com/yang_yu_xiang/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/index.html"><meta property="og:site_name" content="Yang&#39;s Blog"><meta property="og:description" content="1.什么是reactive?reactive是Vue3中提供的实现响应式数据的方法在Vue2中响应式数据是通过defineProperty来实现的,而在Vue3中响应式数据是通过ES6的Proxy来实现的reactive注意点:reactive参数必须是对象或数组(json&#x2F;arr)，否则无法变成响应式如果给reactive传递了其它对象,默认情况下修改对象，界面不会自动更新。如果想更新，可以通过"><meta property="og:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/reactiveproxy.png"><meta property="og:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/%E9%80%92%E5%BD%92%E7%9B%91%E5%90%AC.png"><meta property="og:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/%E9%80%92%E5%BD%92%E7%9B%91%E5%90%AC2.png"><meta property="og:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/%E9%80%92%E5%BD%92%E7%9B%91%E5%90%AC3.png"><meta property="og:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/shallowref.png"><meta property="article:published_time" content="2020-10-28T13:25:00.000Z"><meta property="article:modified_time" content="2020-10-30T15:10:07.189Z"><meta property="article:author" content="杨雨翔"><meta property="article:tag" content="Vue"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/reactiveproxy.png"><script type="text/javascript" id="hexo.configurations">var NexT=window.NexT||{},CONFIG={root:"/MyBlog/",scheme:"Gemini",version:"5.1.4",sidebar:{position:"left",display:"post",offset:12,b2t:!1,scrollpercent:!0,onmobile:!0},fancybox:!0,tabs:!0,motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}},duoshuo:{userId:"0",author:"博主"},algolia:{applicationID:"",apiKey:"",indexName:"",hits:{per_page:10},labels:{input_placeholder:"Search for Posts",hits_empty:"We didn't find any results for the search: ${query}",hits_stats:"${hits} results found in ${time} ms"}}}</script><link rel="canonical" href="https://gitee.com/yang_yu_xiang/MyBlog/2020/10/28/Vue3-0（三）ref和reactive/"><title>Vue3.0（三）reactive和ref | Yang's Blog</title><meta name="generator" content="Hexo 4.2.1"></head><body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans"><div class="container sidebar-position-left page-post-detail"><div class="headband"></div><a href="https://gitee.com/yang_yu_xiang" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513;color:#fff;position:absolute;top:0;border:0;right:0" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style><header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-wrapper"><div class="site-meta"><div class="custom-logo-site-title"><a href="/MyBlog/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Yang's Blog</span> <span class="logo-line-after"><i></i></span></a></div><p class="site-subtitle">永远年轻 永远热泪盈眶</p></div><div class="site-nav-toggle"><button><span class="btn-bar"></span> <span class="btn-bar"></span> <span class="btn-bar"></span></button></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/MyBlog/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i><br>首页</a></li><li class="menu-item menu-item-tags"><a href="/MyBlog/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br>标签</a></li><li class="menu-item menu-item-categories"><a href="/MyBlog/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br>分类</a></li><li class="menu-item menu-item-archives"><a href="/MyBlog/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br>归档</a></li><li class="menu-item menu-item-search"><a href="javascript:;" class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br>搜索</a></li></ul><div class="site-search"><div class="popup search-popup local-search-popup"><div class="local-search-header clearfix"><span class="search-icon"><i class="fa fa-search"></i> </span><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span><div class="local-search-input-wrapper"><input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input"></div></div><div id="local-search-result"></div></div></div></nav></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="https://gitee.com/yang_yu_xiang/MyBlog/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="杨雨翔"><meta itemprop="description" content=""><meta itemprop="image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/psb.jpg"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Yang's Blog"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">Vue3.0（三）reactive和ref</h1><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2020-10-28T21:25:00+08:00">2020-10-28 </time><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-calendar-check-o"></i> </span><span class="post-meta-item-text">更新于&#58;</span> <time title="更新于" itemprop="dateModified" datetime="2020-10-30T23:10:07+08:00">2020-10-30 </time></span><span class="post-comments-count"><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-comment-o"></i> </span><a href="/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/#comments" itemprop="discussionUrl"><span class="post-comments-count valine-comment-count" data-xid="/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/" itemprop="commentCount"></span> </a></span><span class="post-meta-divider">|</span> <span class="page-pv">本文总阅读数 <i class="fa fa-file-o"></i> <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>次</span><div class="post-wordcount"><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i> </span><span class="post-meta-item-text">字数统计&#58;</span> <span title="字数统计">2.3k </span><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-clock-o"></i> </span><span class="post-meta-item-text">阅读时长 &asymp;</span> <span title="阅读时长">10</span></div></div></header><div class="post-body" itemprop="articleBody"><h1 id="1-什么是reactive"><a href="#1-什么是reactive" class="headerlink" title="1.什么是reactive?"></a>1.什么是reactive?</h1><ul><li>reactive是Vue3中提供的实现响应式数据的方法</li><li>在Vue2中响应式数据是通过<code>defineProperty</code>来实现的,而在Vue3中响应式数据是通过ES6的Proxy来实现的</li></ul><h1 id="reactive注意点"><a href="#reactive注意点" class="headerlink" title="reactive注意点:"></a>reactive注意点:</h1><ul><li><code>reactive</code>参数<strong>必须是对象或数组</strong>(json/arr)，否则无法变成响应式</li><li>如果给reactive传递了其它对象,默认情况下修改对象，界面不会自动更新。如果想更新，可以通过重新赋值的方式</li></ul><h1 id="使用reactive"><a href="#使用reactive" class="headerlink" title="使用reactive"></a>使用reactive</h1><h2 id="基本类型的使用"><a href="#基本类型的使用" class="headerlink" title="基本类型的使用"></a>基本类型的使用</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123;msg&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"clickFun"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; reactive &#125; <span class="keyword">from</span> <span class="string">'vue'</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = reactive(<span class="number">0</span>)</span></span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">clickFun</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">      msg++;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      clickFun</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><a id="more"></a><p>&emsp;&emsp;以上这个实例,点击这个按钮不会有变化,一直是0。因为<code>reactive</code>参数不是对象或数组，基本类型（数字、字符串、布尔值）在 <code>reactive</code>中无法被创建成<code>proxy</code>对象，也就无法实现监听(无法实现响应式数据)。<br>&emsp;&emsp;如果是 <code>ref</code>的话，就不存在这样的问题。而如果要使用 <code>reactive</code> ，我们需要将参数从 基本类型 转化为 对象。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123;msg.num&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"clickFun"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; reactive &#125; <span class="keyword">from</span> <span class="string">'vue'</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = reactive(&#123;</span></span><br><span class="line">      num: 0</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">clickFun</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">      msg.num ++;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      clickFun</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>将参数替换成了对象 {num: 0}，此时，点击按钮界面就会产生改变。查看控制台：</p><p><img src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/reactiveproxy.png" alt=""></p><p>可以看到，<code>msg</code>成功被创建成了 <code>proxy</code>对象，他通过劫持对象的 <code>get</code> 和 <code>set</code> 方法实现了对象的双向数据绑定。</p><h2 id="在-reactive-使用-Date-参数"><a href="#在-reactive-使用-Date-参数" class="headerlink" title="在 reactive 使用 Date 参数"></a>在 reactive 使用 Date 参数</h2><p>&emsp;&emsp;如果参数不是数组、对象，而是稍微奇怪一点的数据类型，例如说 <code>Date</code> ，那么麻烦又来了。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123;msg&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"clickFun"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; reactive &#125; <span class="keyword">from</span> <span class="string">'vue'</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = reactive(<span class="keyword">new</span> <span class="built_in">Date</span>())</span></span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">clickFun</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">      msg.setDate(msg.getDate() + 1);</span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      clickFun</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>点击一次 button ，<code>msg</code>的数据是存在变化的，但界面并未发生变化，同时我们发现在控制台里，<code>msg</code> 并未被识别成 <code>proxy。</code></p><p>就算我们把 <code>Date</code> 放在对象里，就像这样</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//  &lt;p&gt;&#123;&#123;msg.data&#125;&#125;&lt;/p&gt;</span></span><br><span class="line"><span class="keyword">let</span> msg = reactive(&#123;</span><br><span class="line">    date: <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>也无法起作用，显然，对于这种数据类型，我们需要做特殊处理。这个特殊处理就是重新赋值（<strong>而不是直接修改原来的值</strong>）。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123;msg.date&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"clickFun"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; reactive &#125; <span class="keyword">from</span> <span class="string">'vue'</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = reactive(&#123;</span></span><br><span class="line"><span class="javascript">      date: <span class="keyword">new</span> <span class="built_in">Date</span>()</span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">clickFun</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">      msg.date.setDate((msg.date.getDate() + 1));</span><br><span class="line"><span class="javascript">      msg.date = <span class="keyword">new</span> <span class="built_in">Date</span>(msg.date);</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      clickFun</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这里我采用了拷贝的方案重新赋值了 <code>msg.date</code>，界面成功发生了变化（日期 +1）。</p><h1 id="ref"><a href="#ref" class="headerlink" title="ref"></a>ref</h1><ul><li><code>ref</code> 和 <code>reactive</code> 一样，也是用来实现响应式数据的方法</li><li>由于 <code>reactive</code> 必须传递一个对象，所以导致在企业开发中，如果我们只想让某个变量实现响应式的时候会非常麻烦，而<code>ref</code>就能实现对简单值的监听。<h2 id="ref的本质"><a href="#ref的本质" class="headerlink" title="ref的本质"></a>ref的本质</h2></li><li><code>ref</code>底层的本质其实还是<code>reactive</code></li><li>系统会自动根据我们给<code>ref</code>传入的值将它转换成<strong>ref(xx) -&gt; reactive({value : xx})</strong>，所以当我们修改对象的值的的时候需要使用<code>xx.value</code>，但是在template模板中使用时，vue3自动帮我们加上了value,直接即可<h2 id="ref和reactive的比较使用"><a href="#ref和reactive的比较使用" class="headerlink" title="ref和reactive的比较使用"></a>ref和reactive的比较使用</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- reactive的写法 &lt;p&gt;&#123;&#123;state.age&#125;&#125;&lt;/p&gt; --&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 下面这里的age已经自动给我们加上了.value，所以我们不用加 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;&#123;age&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"myFn"</span>&gt;</span>按钮<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;refl&#125; <span class="keyword">from</span> <span class="string">'vue '</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name:<span class="string">'App '</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="actionscript">  <span class="comment">//reactive的写法</span></span></span><br><span class="line"><span class="actionscript">  <span class="comment">// let state = reactive(&#123;</span></span></span><br><span class="line"><span class="actionscript">  <span class="comment">//  age:18</span></span></span><br><span class="line"><span class="actionscript">  <span class="comment">// &#125;)</span></span></span><br><span class="line"></span><br><span class="line"><span class="actionscript">  <span class="comment">//ref的写法</span></span></span><br><span class="line"><span class="javascript">  <span class="keyword">let</span> age = ref(<span class="number">18</span>);</span></span><br><span class="line"><span class="actionscript">  <span class="function"><span class="keyword">function</span> <span class="title">myFn</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="actionscript">    <span class="comment">//reactive的写法</span></span></span><br><span class="line"><span class="actionscript">    <span class="comment">//state.age = 666</span></span></span><br><span class="line"></span><br><span class="line"><span class="actionscript">    <span class="comment">//ref的写法</span></span></span><br><span class="line">    age.value = 666;</span><br><span class="line"><span class="javascript">    <span class="built_in">console</span>.log(age);</span></span><br><span class="line">  &#125;</span><br><span class="line"><span class="actionscript">  <span class="keyword">return</span> &#123;age, myFn&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul><h1 id="ref和reactive的区别"><a href="#ref和reactive的区别" class="headerlink" title="ref和reactive的区别"></a>ref和reactive的区别</h1><p>虽然ref底层是reactive，但是还是有一些差别：</p><ul><li>如果在template里使用的是ref类型的数据，那么Vue会自动帮我们添加.value</li><li>如果在template里使用的是reactive类型的数据，那么Vue不会自动帮我们添加.value</li></ul><p><strong>Vue是如何决定是否需要自动添加.value的</strong>？</p><ul><li>Vue在解析数据之前，会自动判断这个数据是否是ref类型的，如果是就自动添加.value，如果不是就不自动添加.value</li></ul><p><strong>Vue是如何判断当前的数据是否是ref类型的</strong>？</p><ul><li>通过当前数据的__v_ref来判断的，如果对象有这个私有的属性，并且取值为true，那么就代表是一个ref类型的数据</li></ul><p>同时，vue还提供了isRef和isReactive这两个方法来协助我们辨识</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript"><span class="comment">/*1.ref和reactive区别...*/</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;isRef, isReactive&#125; <span class="keyword">from</span> <span class="string">'vue'</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;reactive&#125; <span class="keyword">from</span> <span class="string">'vue '</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;ref&#125; <span class="keyword">from</span> <span class="string">'vue '</span>;</span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name:<span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> age = ref(<span class="number">18</span>);</span></span><br><span class="line"><span class="actionscript">    <span class="comment">// let age = reactive(&#123;value:18&#125;);</span></span></span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">myFn</span><span class="params">()</span></span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(isRef(age));<span class="comment">//true</span></span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(isReactive(age));<span class="comment">//false</span></span></span><br><span class="line">      lage.value = 666;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="actionscript">  <span class="keyword">return</span> &#123;age,myFn&#125;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="递归监听"><a href="#递归监听" class="headerlink" title="递归监听"></a>递归监听</h1><p>&emsp;&emsp;<strong>默认情况下</strong>，Vue3 中的 <code>ref</code> 和 <code>reactive</code> <strong>都是</strong>递归监听的，即能实时监听对象的底层变化。<br>例如，在 <code>ref</code> 中</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.a.b.c = &#123;&#123;msg.a.b.c&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.e.f = &#123;&#123;msg.e.f&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.g = &#123;&#123;msg.g&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"c"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; ref &#125; <span class="keyword">from</span> <span class="string">'vue'</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = ref(&#123;</span></span><br><span class="line">      a: &#123;</span><br><span class="line">        b: &#123;</span><br><span class="line"><span class="actionscript">          c: <span class="string">'c'</span></span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      e: &#123;</span><br><span class="line"><span class="actionscript">        f: <span class="string">'f'</span></span></span><br><span class="line">      &#125;,</span><br><span class="line"><span class="actionscript">      g: <span class="string">'g'</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">c</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line"><span class="actionscript">      msg.value.a.b.c = <span class="string">'C'</span>;</span></span><br><span class="line"><span class="actionscript">      msg.value.e.f = <span class="string">'F'</span>;</span></span><br><span class="line"><span class="actionscript">      msg.value.g = <span class="string">'G'</span>;</span></span><br><span class="line">    &#125;;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      c</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p><img src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/%E9%80%92%E5%BD%92%E7%9B%91%E5%90%AC.png" alt=""></p><p>当我们点击<code>button</code>,变成下面这样：</p><p><img src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/%E9%80%92%E5%BD%92%E7%9B%91%E5%90%AC2.png" alt=""></p><h2 id="递归监听存在的问题："><a href="#递归监听存在的问题：" class="headerlink" title="递归监听存在的问题："></a>递归监听存在的问题：</h2><p>&emsp;&emsp;如果数据量比较大，非常消耗性能，Vue3递归了对象中的每一层的值，包装成一个<code>proxy</code>对象,我们可以在上个例子中log出对象看看：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(msg.a);</span><br><span class="line"><span class="built_in">console</span>.log(msg.gf.b);</span><br><span class="line"><span class="built_in">console</span>.log(msg.gf.f.c);</span><br><span class="line"><span class="built_in">console</span>.log(msg.gf.f.s.d);</span><br></pre></td></tr></table></figure><p>我们看控制台：<br><img src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/%E9%80%92%E5%BD%92%E7%9B%91%E5%90%AC3.png" alt=""></p><p>Vue把每一层数据都包装成了<code>proxy</code>对象,所以比较消耗性能</p><h1 id="非递归监听"><a href="#非递归监听" class="headerlink" title="非递归监听"></a>非递归监听</h1><h2 id="shallowReactive和-shallowRef"><a href="#shallowReactive和-shallowRef" class="headerlink" title="shallowReactive和 shallowRef"></a>shallowReactive和 shallowRef</h2><p>&emsp;&emsp;非递归监听需要用到<code>shallowReactive</code>、 <code>shallowRef</code>。我们把上面的例子用非递归监听改造一下：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.a.b.c = &#123;&#123;msg.a.b.c&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.e.f = &#123;&#123;msg.e.f&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.g = &#123;&#123;msg.g&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"c"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;shallowReactivel&#125; <span class="keyword">from</span> <span class="string">' vue '</span> ;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123;shallowRef&#125; <span class="keyword">from</span> <span class="string">' vue'</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = shallowRef(&#123;</span></span><br><span class="line">      a: &#123;</span><br><span class="line">        b: &#123;</span><br><span class="line"><span class="actionscript">          c: <span class="string">'c'</span></span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      e: &#123;</span><br><span class="line"><span class="actionscript">        f: <span class="string">'f'</span></span></span><br><span class="line">      &#125;,</span><br><span class="line"><span class="actionscript">      g: <span class="string">'g'</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">c</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line"><span class="actionscript">      msg.value.a.b.c = <span class="string">'C'</span>;</span></span><br><span class="line"><span class="actionscript">      msg.value.e.f = <span class="string">'F'</span>;</span></span><br><span class="line"><span class="actionscript">      msg.value.g = <span class="string">'G'</span>;</span></span><br><span class="line">    &#125;;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      c</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这样，我们就监听不到下面几层的变化，所以数据不会发生改变</p><p><img src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/shallowref.png" alt=""></p><p>&emsp;&emsp;打开控制台我们注意到，此时的 RefImpl 对象（控制台里显示的那个对象）上 _shallow 值变为 true 。此时，由于只有最外层的数据改变能被监测到，所以只有在<strong>直接改变 <code>msg.value</code></strong> 的时候才会产生监测。</p><h2 id="triggerRef"><a href="#triggerRef" class="headerlink" title="triggerRef"></a>triggerRef</h2><p>&emsp;&emsp;除此之外，对于<code>shallow</code>过的 <code>ref</code>对象，我们还可以手动去触发ref的变化监听事件来实现界面的改变。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.a.b.c = &#123;&#123;msg.a.b.c&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.e.f = &#123;&#123;msg.e.f&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>msg.g = &#123;&#123;msg.g&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"c"</span>&gt;</span>button<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript"><span class="keyword">import</span> &#123; ref, shallowRef, triggerRef &#125; <span class="keyword">from</span> <span class="string">'vue'</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="actionscript">  name: <span class="string">'App'</span>,</span></span><br><span class="line">  setup() &#123;</span><br><span class="line"><span class="javascript">    <span class="keyword">let</span> msg = shallowRef(&#123;</span></span><br><span class="line">      a: &#123;</span><br><span class="line">        b: &#123;</span><br><span class="line"><span class="actionscript">          c: <span class="string">'c'</span></span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      e: &#123;</span><br><span class="line"><span class="actionscript">        f: <span class="string">'f'</span></span></span><br><span class="line">      &#125;,</span><br><span class="line"><span class="actionscript">      g: <span class="string">'g'</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="actionscript">    <span class="function"><span class="keyword">function</span> <span class="title">c</span><span class="params">()</span> </span>&#123;</span></span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line"><span class="actionscript">      msg.value.a.b.c = <span class="string">'C'</span>;</span></span><br><span class="line"><span class="actionscript">      msg.value.e.f = <span class="string">'F'</span>;</span></span><br><span class="line"><span class="actionscript">      msg.value.g = <span class="string">'G'</span>;</span></span><br><span class="line">      triggerRef(msg);</span><br><span class="line"><span class="javascript">      <span class="built_in">console</span>.log(msg);</span></span><br><span class="line">    &#125;;</span><br><span class="line"><span class="actionscript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line">      msg,</span><br><span class="line">      c</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p><strong>注意点</strong>:</p><p>&emsp;&emsp;Vue3只提供了<code>triggerRef</code>方法，没有提供<code>triggerReactive方法</code>，所以如果是<code>reactive</code>类型的数据，那么是无法主动触发界面更新的</p><h2 id="shallowRef的本质"><a href="#shallowRef的本质" class="headerlink" title="shallowRef的本质"></a>shallowRef的本质</h2><p>在之前说过，<code>ref</code>的本质是<code>reactive</code></p><ul><li>ref -&gt; reactive</li><li>ref(10)-&gt; reactive({value: 10})</li><li>shallowRef -&gt;shallowReactive</li><li>shallowRef(10) -&gt;shallowReactive({value: 10})</li><li>所以如果是通过shallowRef创建的数据，它监听的是.value的变化,因为底层本质上value才是第一层</li></ul></div><div><div class="my_post_copyright"><script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script><script src="https://cdn.bootcss.com/jquery/2.0.0/jquery.min.js"></script><script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script><p><span>本文标题:</span><a href="/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/">Vue3.0（三）reactive和ref</a></p><p><span>文章作者:</span><a href="/" title="访问 杨雨翔 的个人博客">杨雨翔</a></p><p><span>发布时间:</span>2020年10月28日 - 21:25</p><p><span>最后更新:</span>2020年10月30日 - 23:10</p><p><span>原始链接:</span><a href="/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/" title="Vue3.0（三）reactive和ref">https://gitee.com/yang_yu_xiang/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/</a> <span class="copy-path" title="点击复制文章链接"><i class="fa fa-clipboard" data-clipboard-text="https://gitee.com/yang_yu_xiang/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%B8%89%EF%BC%89ref%E5%92%8Creactive/" aria-label="复制成功！"></i></span></p><p><span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p></div><script>var clipboard=new Clipboard(".fa-clipboard");$(".fa-clipboard").click((function(){clipboard.on("success",(function(){swal({title:"",text:"复制成功",icon:"success",showConfirmButton:!0})}))}))</script></div><div style="text-align:center;color:#ccc;font-size:16px">---------------- The End ----------------</div><footer class="post-footer"><div class="post-tags"><a href="/MyBlog/tags/Vue/" rel="tag"><i class="fa fa-tag"></i> Vue</a></div><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/MyBlog/2020/10/28/Vue3-0%EF%BC%88%E4%BA%8C%EF%BC%89%E7%BB%84%E5%90%88API/" rel="next" title="Vue3.0（二）组合API(Composition API)"><i class="fa fa-chevron-left"></i> Vue3.0（二）组合API(Composition API)</a></div><span class="post-nav-divider"></span><div class="post-nav-prev post-nav-item"><a href="/MyBlog/2020/10/29/Vue3-0%EF%BC%88%E5%9B%9B%EF%BC%89toRaw/" rel="prev" title="Vue3.0（四）toRaw">Vue3.0（四）toRaw <i class="fa fa-chevron-right"></i></a></div></div></footer></div></article><div class="post-spread"><div class="jiathis_style"><span class="jiathis_txt">分享到：</span> <a class="jiathis_button_fav">收藏夹</a> <a class="jiathis_button_copy">复制网址</a> <a class="jiathis_button_email">邮件</a> <a class="jiathis_button_weixin">微信</a> <a class="jiathis_button_qzone">QQ空间</a> <a class="jiathis_button_tqq">腾讯微博</a> <a class="jiathis_button_douban">豆瓣</a> <a class="jiathis_button_share">一键分享</a> <a href="http://www.jiathis.com/share?uid=2140465" class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis" target="_blank">更多</a> <a class="jiathis_counter_style"></a></div><script type="text/javascript">var jiathis_config={data_track_clickback:!0,summary:"",shortUrl:!1,hideMore:!1}</script><script type="text/javascript" src="http://v3.jiathis.com/code/jia.js?uid=" charset="utf-8"></script></div></div></div><div class="comments" id="comments"></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span> <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span> <span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div id="sidebar-dimmer"></div><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">文章目录</li><li class="sidebar-nav-overview" data-target="site-overview-wrap">站点概览</li></ul><section class="site-overview-wrap sidebar-panel"><div class="site-overview"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"><img class="site-author-image" itemprop="image" src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/psb.jpg" alt="杨雨翔"><p class="site-author-name" itemprop="name">杨雨翔</p><p class="site-description motion-element" itemprop="description"></p></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"><a href="/MyBlog/archives/"><span class="site-state-item-count">53</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"><a href="/MyBlog/categories/index.html"><span class="site-state-item-count">12</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"><a href="/MyBlog/tags/index.html"><span class="site-state-item-count">32</span> <span class="site-state-item-name">标签</span></a></div></nav><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://gitee.com/yang_yu_xiang" target="_blank" title="码云"><i class="fa fa-fw fa-git"></i>码云</a> </span><span class="links-of-author-item"><a href="http://wpa.qq.com/msgrd?v=3&uin=1372201820&site=qq&menu=yes" target="_blank" title="QQ"><i class="fa fa-fw fa-qq"></i>QQ</a> </span><span class="links-of-author-item"><a href="https://github.com/gezhicui" target="_blank" title="Github"><i class="fa fa-fw fa-github"></i>Github</a> </span><span class="links-of-author-item"><a href="mailto:1372201820@qq.com" target="_blank" title="E-Mail"><i class="fa fa-fw fa-envelope"></i>E-Mail</a></span></div><div class="links-of-blogroll motion-element links-of-blogroll-block"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-link"></i> 友情链接</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"><a href="https://cloudhao.top/#/search/%E5%9F%9F%E5%90%8D" title="陈昀昊的小窝" target="_blank">陈昀昊的小窝</a></li><li class="links-of-blogroll-item"><a href="http://www.shezhiwei.top/" title="佘智伟的博客" target="_blank">佘智伟的博客</a></li><li class="links-of-blogroll-item"><a href="https://blog.csdn.net/qq_43185206" title="阿呆的小鸡仔" target="_blank">阿呆的小鸡仔</a></li></ul></div></div></section><section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active"><div class="post-toc"><div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#1-什么是reactive"><span class="nav-number">1.</span> <span class="nav-text">1.什么是reactive?</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#reactive注意点"><span class="nav-number">2.</span> <span class="nav-text">reactive注意点:</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#使用reactive"><span class="nav-number">3.</span> <span class="nav-text">使用reactive</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#基本类型的使用"><span class="nav-number">3.1.</span> <span class="nav-text">基本类型的使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#在-reactive-使用-Date-参数"><span class="nav-number">3.2.</span> <span class="nav-text">在 reactive 使用 Date 参数</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#ref"><span class="nav-number">4.</span> <span class="nav-text">ref</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#ref的本质"><span class="nav-number">4.1.</span> <span class="nav-text">ref的本质</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#ref和reactive的比较使用"><span class="nav-number">4.2.</span> <span class="nav-text">ref和reactive的比较使用</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#ref和reactive的区别"><span class="nav-number">5.</span> <span class="nav-text">ref和reactive的区别</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#递归监听"><span class="nav-number">6.</span> <span class="nav-text">递归监听</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#递归监听存在的问题："><span class="nav-number">6.1.</span> <span class="nav-text">递归监听存在的问题：</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#非递归监听"><span class="nav-number">7.</span> <span class="nav-text">非递归监听</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#shallowReactive和-shallowRef"><span class="nav-number">7.1.</span> <span class="nav-text">shallowReactive和 shallowRef</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#triggerRef"><span class="nav-number">7.2.</span> <span class="nav-text">triggerRef</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#shallowRef的本质"><span class="nav-number">7.3.</span> <span class="nav-text">shallowRef的本质</span></a></li></ol></li></ol></div></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright">&copy; <span itemprop="copyrightYear">2021</span> <span class="with-love"><i class="fa fa-send"></i> </span><span class="author" itemprop="copyrightHolder">杨雨翔</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-area-chart"></i> </span><span class="post-meta-item-text">站点总字数&#58;</span> <span title="站点总字数">61.9k</span></div><div class="busuanzi-count"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="site-uv">本站访问数 <i class="fa fa-user"></i> <span class="busuanzi-value" id="busuanzi_value_site_uv"></span> 人次 </span><span class="site-pv">本站总访问量 <i class="fa fa-eye"></i> <span class="busuanzi-value" id="busuanzi_value_site_pv"></span> 次</span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i> <span id="scrollpercent"><span>0</span>%</span></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/MyBlog/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/MyBlog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/MyBlog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/MyBlog/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/MyBlog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/MyBlog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/MyBlog/js/src/utils.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/motion.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/affix.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/schemes/pisces.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/scrollspy.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/post-details.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/bootstrap.js?v=5.1.4"></script><script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script><script src="//unpkg.com/valine/dist/Valine.min.js"></script><script type="text/javascript">var GUEST=["nick","mail","link"],guest="nick";guest=guest.split(",").filter(e=>GUEST.indexOf(e)>-1),new Valine({el:"#comments",verify:!1,notify:!1,appId:"i5Tl5zN4f4LxoJgipanUuaml-gzGzoHsz",appKey:"wqw6uYNCQkeVxBffKebM29NH",placeholder:"说点什么吧...",avatar:"mm",guest_info:guest,pageSize:"10"})</script><script type="text/javascript">var isfetched=!1,isXml=!0,search_path="search.xml";0===search_path.length?search_path="search.xml":/json$/i.test(search_path)&&(isXml=!1);var path="/MyBlog/"+search_path,onPopupClose=function(t){$(".popup").hide(),$("#local-search-input").val(""),$(".search-result-list").remove(),$("#no-result").remove(),$(".local-search-pop-overlay").remove(),$("body").css("overflow","")};function proceedsearch(){$("body").append('<div class="search-popup-overlay local-search-pop-overlay"></div>').css("overflow","hidden"),$(".search-popup-overlay").click(onPopupClose),$(".popup").toggle();var t=$("#local-search-input");t.attr("autocapitalize","none"),t.attr("autocorrect","off"),t.focus()}var searchFunc=function(t,e,o){"use strict";$("body").append('<div class="search-popup-overlay local-search-pop-overlay"><div id="search-loading-icon"><i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i></div></div>').css("overflow","hidden"),$("#search-loading-icon").css("margin","20% auto 0 auto").css("text-align","center"),$.ajax({url:t,dataType:isXml?"xml":"json",async:!0,success:function(t){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var n=isXml?$("entry",t).map((function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}})).get():t,r=document.getElementById(e),s=document.getElementById(o),a=function(){var t=r.value.trim().toLowerCase(),e=t.split(/[\s\-]+/);e.length>1&&e.push(t);var o=[];if(t.length>0&&n.forEach((function(n){var r=!1,s=0,a=0,i=n.title.trim(),c=i.toLowerCase(),l=n.content.trim().replace(/<[^>]+>/g,""),h=l.toLowerCase(),p=decodeURIComponent(n.url),u=[],f=[];if(""!=i&&(e.forEach((function(t){function e(t,e,o){var n=t.length;if(0===n)return[];var r=0,s=[],a=[];for(o||(e=e.toLowerCase(),t=t.toLowerCase());(s=e.indexOf(t,r))>-1;)a.push({position:s,word:t}),r=s+n;return a}u=u.concat(e(t,c,!1)),f=f.concat(e(t,h,!1))})),(u.length>0||f.length>0)&&(r=!0,s=u.length+f.length)),r){function d(e,o,n,r){for(var s=r[r.length-1],i=s.position,c=s.word,l=[],h=0;i+c.length<=n&&0!=r.length;){c===t&&h++,l.push({position:i,length:c.length});var p=i+c.length;for(r.pop();0!=r.length&&(i=(s=r[r.length-1]).position,c=s.word,p>i);)r.pop()}return a+=h,{hits:l,start:o,end:n,searchTextCount:h}}[u,f].forEach((function(t){t.sort((function(t,e){return e.position!==t.position?e.position-t.position:t.word.length-e.word.length}))}));var g=[];0!=u.length&&g.push(d(0,0,i.length,u));for(var v=[];0!=f.length;){var $=f[f.length-1],C=$.position,m=$.word,x=C-20,w=C+80;x<0&&(x=0),w<C+m.length&&(w=C+m.length),w>l.length&&(w=l.length),v.push(d(0,x,w,f))}v.sort((function(t,e){return t.searchTextCount!==e.searchTextCount?e.searchTextCount-t.searchTextCount:t.hits.length!==e.hits.length?e.hits.length-t.hits.length:t.start-e.start}));var y=parseInt("1");function T(t,e){var o="",n=e.start;return e.hits.forEach((function(e){o+=t.substring(n,e.position);var r=e.position+e.length;o+='<b class="search-keyword">'+t.substring(e.position,r)+"</b>",n=r})),o+=t.substring(n,e.end)}y>=0&&(v=v.slice(0,y));var b="";0!=g.length?b+="<li><a href='"+p+"' class='search-result-title'>"+T(i,g[0])+"</a>":b+="<li><a href='"+p+"' class='search-result-title'>"+i+"</a>",v.forEach((function(t){b+="<a href='"+p+'\'><p class="search-result">'+T(l,t)+"...</p></a>"})),b+="</li>",o.push({item:b,searchTextCount:a,hitCount:s,id:o.length})}})),1===e.length&&""===e[0])s.innerHTML='<div id="no-result"><i class="fa fa-search fa-5x" /></div>';else if(0===o.length)s.innerHTML='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>';else{o.sort((function(t,e){return t.searchTextCount!==e.searchTextCount?e.searchTextCount-t.searchTextCount:t.hitCount!==e.hitCount?e.hitCount-t.hitCount:e.id-t.id}));var a='<ul class="search-result-list">';o.forEach((function(t){a+=t.item})),a+="</ul>",s.innerHTML=a}};r.addEventListener("input",a),$(".local-search-pop-overlay").remove(),$("body").css("overflow",""),proceedsearch()}})};$(".popup-trigger").click((function(t){t.stopPropagation(),!1===isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()})),$(".popup-btn-close").click(onPopupClose),$(".popup").click((function(t){t.stopPropagation()})),$(document).on("keyup",(function(t){27===t.which&&$(".search-popup").is(":visible")&&onPopupClose()}))</script><script src="/MyBlog/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"model":{"jsonPath":"/MyBlog/live2dw/assets/wanko.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"log":false});</script></body></html>